/*
 *  logger4cpp - Simple C++ Logger
 *
 *  Copyright (C) 2011 CodeFutures Corporation. All rights reserved.
 */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <map>

#include <logger/Logger.h>

namespace logger4cpp {

Logger::Logger(string name, int logLevel) {

	this->name = name;

#ifdef DEBUG_LOGGER
    cerr << "Initializing Logger '" << name << "' with level " << logLevel << endl;
#endif

    isTrace = logLevel > LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_TRACE;
    isDebug = logLevel > LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_DEBUG;
    isInfo = logLevel > LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_INFO;
    isWarn = logLevel > LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_WARN;
    isError = logLevel > LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_ERROR;
}

Logger::~Logger() {
}

bool Logger::isTraceEnabled() {
    return isTrace;
}

bool Logger::isDebugEnabled() {
    return isDebug;
}

bool Logger::isInfoEnabled() {
    return isInfo;
}

bool Logger::isWarnEnabled() {
    return isWarn;
}

void Logger::trace(string message) {
	trace(message.c_str());
}

void Logger::debug(string message) {
	debug(message.c_str());
}

void Logger::info(string message) {
	info(message.c_str());
}

void Logger::warn(string message) {
	warn(message.c_str());
}

void Logger::error(string message) {
	error(message.c_str());
}

/*static*/ string Logger::getTimestamp() {

	time_t rawtime;
	struct tm * timeinfo;

	time ( &rawtime );
	timeinfo = localtime ( &rawtime );

	//TODO do we need a mutex around the call to asctime?
	string ret = string(asctime(timeinfo));
	
	// remove \n from end of string
	ret = ret.substr(0, ret.size()-1);
	
	return string("[") + ret + string("] ");
}

// get process-id and thread-id
string getPidTid() {
    char temp[256];
#ifdef __APPLE__
    sprintf(temp, "[PID:N/A]");
#else
    sprintf(temp, "[PID:%d] [TID:%u]", getpid(), (unsigned int)pthread_self());
#endif
    return string(temp);
}

void Logger::log(const char *level, const char *message) {

    // mutex for thread-safety so we only write one line at a time
//	boost::mutex::scoped_lock lock(logMutex);

	if (file==NULL) {
	    cerr << "[" << (time(NULL)-timeStart) << "s] " << getPidTid().c_str() << " [" << level << "] [" << name << "] " << message << endl;
    }
    else {

    	fprintf(file, "[%ld s] %s [%s] [%s] %s\n", time(NULL), getPidTid().c_str(), level, name.c_str(), message);
    	lineCount++;

        // uncomment this line to flush after each write to help track down errors that cause the process to die
        fflush(file);
    }
}

void Logger::trace(const char *message) {
    log("TRACE", message);
}

void Logger::debug(const char *message) {
    log("DEBUG", message);
}

void Logger::info(const char *message) {
    log("INFO", message);
}

void Logger::warn(const char *message) {
    log("WARN", message);
}

void Logger::error(const char *message) {
    log("ERROR", message);
}

} // namespace
